// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using PfRep.Common;
using System.IO;
using System.Threading;
using System.Reflection;
using System.Data.SqlClient;

namespace PfRep.Console
{
    public partial class Options : Form
    {
        #region Connection String parameter name constants
        private const string propServer = "server";
        private const string propDatabase = "database";
        private const string propIntegratedSecurity = "Integrated Security";
        private const string propUsername = "uid";
        private const string propPassword = "password";
        #endregion
        
        private bool cancelled = false;
        
        /// <summary>
        /// Indicates whether this is the first time the tool is started
        /// </summary>
        private bool firstTimeUse = false;

        /// <summary>
        /// An alternative connection string where the 
        ///  database points to master. This can be used to test
        ///  whether the server exists but the database doesn't
        /// </summary>
        private string masterConnectionString = "";

        private OptionsDialogDisplayMode displayMode;

        #region Public members
        /// <summary>
        /// Describes the purpose the option dialog opened for
        /// </summary>
        public enum OptionsDialogDisplayMode
        {
            /// <summary>
            /// Shows all options
            /// </summary>
            All,

            /// <summary>
            /// Shows only connection string options
            /// </summary>
            ConnectionString
        }

        /// <summary>
        /// Sets the dialog's display mode
        /// </summary>
        public OptionsDialogDisplayMode DisplayMode
        {
            get { return displayMode; }
            set { displayMode = value; }
        }

        /// <summary>
        /// Indicates whether the dialog was cancelled
        /// </summary>
        public bool Cancelled
        {
            get { return cancelled; }
        }

        /// <summary>
        /// An alternative connection string where the 
        ///  database points to master. This can be used to test
        ///  whether the server exists but the database doesn't
        /// </summary>
        public bool FirstTimeUse
        {
            get { return firstTimeUse; }
        }

        /// <summary>
        /// An alternative connection string where the 
        ///  database points to master. This can be used to test
        ///  whether the server exists but the database doesn't
        /// </summary>
        public string MasterConnectionString
        {
            get { return masterConnectionString; }
        }
        #endregion

        public Options()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Click on OK button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdOK_Click(object sender, EventArgs e)
        {
            const string connectionStringSchema = "{0}={1};{2}={3};{4}={5};{6};{7}";

            // Indicate that this is not a Cancel operation
            cancelled = false;

            // Assemble query string
            string connectionString = string.Format(connectionStringSchema,
                propServer,
                txtServer.Text,
                propDatabase,
                txtDatabase.Text,
                propIntegratedSecurity,
                (chkUseWindowsAuth.Checked ? "true" : "false"),
                (chkUseWindowsAuth.Checked ? "" : propUsername + "=" + txtUsername.Text),
                (chkUseWindowsAuth.Checked ? "" : propPassword + "=" + txtPassword.Text));

            // Check whether the database specified exists
            bool databaseExists = Library.Management.IsDatabaseExists(connectionString);

            // Assemble an alternative connection string where the 
            //  database points to master. This can be used to test
            //  whether the server exists but the database doesn't
            if (firstTimeUse &&
                !databaseExists &&
                MessageBox.Show("Do you want to create the database?", "PfRep", 
                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                // Assemble the master connection string
                masterConnectionString = string.Format(connectionStringSchema,
                    propServer,
                    txtServer.Text,
                    propDatabase,
                    "master",
                    propIntegratedSecurity,
                    (chkUseWindowsAuth.Checked ? "true" : "false"),
                    (chkUseWindowsAuth.Checked ? "" : propUsername + "=" + txtUsername.Text),
                    (chkUseWindowsAuth.Checked ? "" : propPassword + "=" + txtPassword.Text));

                // Creates the database and objects
                try
                {
                    // Create the database
                    PfRep.Library.Management.CreatePfRepDatabase(masterConnectionString, txtDatabase.Text);

                    // Inform the user that the database creation was succeeded
                    MessageBox.Show("Database succesfully created.", "PfRep",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (SqlException)
                {
                    MessageBox.Show("SQL Server cannot be contacted or permission denied.",
                        "PfRep", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
            }

            // Write back to config file
            Config.SetConfigValue(Config.PARAM_SQL_SERVER_CONNECTIONSTRING, connectionString);

            // Close window
            this.Close();
        }

        /// <summary>
        /// Form initialization
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Options_Load(object sender, EventArgs e)
        {
            // Hide the tabs based on the dialog's display mode
            if (DisplayMode == OptionsDialogDisplayMode.ConnectionString)
            {
                tabControl1.TabPages.Remove(tabControl1.TabPages["tabActionPlan"]);
                this.ActiveControl = txtServer;
            }

            // Retrieve connection string
            string connectionString = Config.GetConfigValue(Config.PARAM_SQL_SERVER_CONNECTIONSTRING);

            // Commented out to make sure that the database is always created
            // If the connection string is null, empty or the default one, we don't disassemble it :)
            /*if (string.IsNullOrEmpty(connectionString) || connectionString.Length == 0 || 
                string.Compare(connectionString, Config.DEFAULT_SQL_CONNECTIONSTRING) == 0)*/
            {
                firstTimeUse = true;
                lblInfoText.Text = lblInfoText.Text +
                    " If the database you specify doesn't exist, it will be created for you.";
                //return;
            }

            // Disassemble connection string to name-value pairs
            string[] connectionStringArray = connectionString.Split(';');

            // Loop thru the name-value pairs in the connection string
            foreach (string variable in connectionStringArray)
            {
                // Convert the name-value pair to a 2 line array (name, value),
                //  then to a value
                string[] prop = variable.Split('=');
                
                // Jump to next loop if the name=value is not complete
                if (prop.Length != 2)
                    continue;
                
                // Variables for storing the name and value parts
                string propName = prop[0];
                string propValue = prop[1];

                // Display the value in the controls
                if (string.Compare(propName, propServer, true) == 0)
                    txtServer.Text = propValue;
                else if (string.Compare(propName, propDatabase, true) == 0)
                    txtDatabase.Text = propValue;
                else if (string.Compare(propName, propIntegratedSecurity, true) == 0)
                    chkUseWindowsAuth.Checked = 
                        (string.Compare(propValue, "true", true) == 0 
                        || string.Compare(propValue, "yes", true) == 0 
                        || string.Compare(propValue, "SSPI", true) == 0);
                else if (string.Compare(propName, propUsername, true) == 0)
                    txtUsername.Text = propValue;
                else if (string.Compare(propName, propPassword, true) == 0)
                    txtPassword.Text = propValue;
            }

            // Set the focus on the server name
            this.ActiveControl = txtServer;
        }

        /// <summary>
        /// Enable/disable the username and password controls based on the
        /// Windows Authentication checkbox's value
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkUseWindowsAuth_CheckedChanged(object sender, EventArgs e)
        {
            txtUsername.Enabled = !chkUseWindowsAuth.Checked;
            txtPassword.Enabled = !chkUseWindowsAuth.Checked;
        }

        /// <summary>
        /// Click on the Cancel button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdCancel_Click(object sender, EventArgs e)
        {
            // Indicate that this is A Cancel operation
            cancelled = true;

            // Close the window
            this.Close();
        }
    }
}